﻿using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Threading;
using MMonitor.PM6750;

namespace MMonitor.BusinessLayer
{
    public class BaseControlV2
    {
        public delegate void ProcessDelegate(ReceivedDataModelV2 rModel);

        readonly SendCodeTransV2 _cds = new SendCodeTransV2();//PM6750发送命令
        private readonly SerialPort _spCom = new SerialPort() { PortName = "COM2", DataBits = 8, StopBits = StopBits.One, Parity = Parity.None };
        private ReceivedDataModelV2 _dRModel = new ReceivedDataModelV2();
        readonly ReceivedCodeTransV2 _rTrans = new ReceivedCodeTransV2();
        private readonly object _spObj = new object();
        private ProcessDelegate _interalPd;
        private Thread _dealThread;//创建独立线程处串口开启之后
        readonly List<byte> _spDataBuff = new List<byte>();//定义新的缓存区

        //PM6750接收数据
        public void OpenPort(ProcessDelegate processDelegate)
        {
            _dealThread = new Thread(StartPortMethod);
            _interalPd = processDelegate;
            _dealThread.Start();
        }

        void StartPortMethod()
        {
            try
            {
                new Thread(new ThreadStart(DealDataBuff)).Start();
                _spCom.Open();
                _spCom.DataReceived += sp_DataReceived;
            }
            catch (Exception)
            {
                return;
            }
        }
        private void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int len = _spCom.BytesToRead; //串口传过来的数据位数
            var bBuff = new byte[len];
            try
            {
                _spCom.Read(bBuff, 0, len);
                _spDataBuff.AddRange(bBuff.ToArray());//将新都区的数据添加到缓存区
            }
            catch (Exception)
            {
                return;
            }
        }
        /// <summary>
        /// 处理缓存区数据函数
        /// </summary>
        void DealDataBuff()
        {
            while (true)
            {
                if (_spDataBuff.Count < 3)
                {
                    continue;
                }
                while (_spDataBuff.Count > 3 && (_spDataBuff[0] != 0x55 || _spDataBuff[1] != 0xAA))
                {
                    //剔除无效数据
                    _spDataBuff.RemoveAt(0);
                }
                while (_spDataBuff.Count > 3 && _spDataBuff[0] == 0x55 && _spDataBuff[1] == 0xAA)
                {
                    try
                    {
                        const byte packageLen = 0x0C;
                        var perBytePackage = _spDataBuff.GetRange(0, packageLen); //浅表复制一个数据包
                        _dRModel = _rTrans.TransReceivedData(perBytePackage.ToArray());
                        _interalPd(_dRModel);
                        _spDataBuff.RemoveRange(0, packageLen); //从缓存区清除已经解析的数据包
                        Thread.Sleep(1);
                    }
                    catch (Exception)
                    {
                        continue; //出错，跳过该包
                    }
                }
            }
        }
        /// <summary>
        /// 关闭串口
        /// </summary>
        public void ClosePort()
        {
            try
            {
                if (_spCom.IsOpen)
                {
                    _dealThread.Abort();//停止串口线程
                    _spCom.DataReceived -= sp_DataReceived;//解绑串口DataReceived事件
                    _spCom.Close();
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        public void NIBPTestStart()
        {
            var tpBts = _cds.GetStartOnceManualTestCode(0);//启动一次成人血压测试
            SendData(tpBts, 0, tpBts.Length);
        }
        public void NIBPTestStop()
        {
            var tpBts = _cds.GetCancleBloodPressureTestCode();//取消血压测试
            SendData(tpBts, 0, tpBts.Length);
        }
        void SendData(byte[] buffer, int offset, int count)
        {
            if (_spCom.IsOpen)
            {
                _spCom.Write(buffer, offset, count);
            }
        }
    }
}
